/*
 * FPGA初始化与通讯
 */
#include "head\FPGA.h"
#include "head\MCU.h"

void FPGA_Init()
{
    /*
     * 复用p104、p105引脚为串口功能
     */
    GPIO_setAsPeripheralModuleFunctionInputPin(
            FPGA_USCI_PORT,
            FPGA_USCI_PIN_TX + FPGA_USCI_PIN_RX
        );

    /*
     * 配置串口
     */
    USCI_A_UART_initParam param = {0};
    param.selectClockSource = USCI_A_UART_CLOCKSOURCE_SMCLK; //选择SMCLK为时钟源
    if(MSP430_FREQUENCY == 25165824)
    {
        param.clockPrescalar = 218;//25,165,824/115200
        param.secondModReg = 4;
    }
    else if(MSP430_FREQUENCY == 16777216)
    {
        param.clockPrescalar = 145;//16,777,216/115200 ~= 145.63555
        param.secondModReg = 5;//0.63555 * 8 ~= 5.08444
    }
    param.firstModReg = 0; //这个是用在过采样波特率模式，公式见用户手册36.3.10.2
    param.parity = USCI_A_UART_NO_PARITY; //奇偶校验 无校验位
    param.msborLsbFirst = USCI_A_UART_LSB_FIRST; //“控制移位寄存器的方向”，及大小端。LSB属于小端，高位字节放高端
    param.numberofStopBits = USCI_A_UART_ONE_STOP_BIT; //停止位数 一个停止位
    param.uartMode = USCI_A_UART_MODE; //普通串口模式
    param.overSampling = USCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION; //低采样波特率或过采样波特率选择
    if (STATUS_FAIL == USCI_A_UART_init(FPGA_USCI_BASE, &param)){
        return;
    }

    /*
     * 使能串口
     */
    USCI_A_UART_enable(FPGA_USCI_BASE);//UCSWRST位置1
    //Enable Receive Interrupt
    USCI_A_UART_clearInterrupt(FPGA_USCI_BASE,USCI_A_UART_RECEIVE_INTERRUPT);//标志位清除
    USCI_A_UART_enableInterrupt(FPGA_USCI_BASE,USCI_A_UART_RECEIVE_INTERRUPT);//使能位置位
    isRxFromRS485 = 0;
}

void FPGA_ReceiveSpectrometer(uint8_t *data)
{
    uint8_t *pFPGA_RxSpBuff;
    uint16_t FPGA_RxSpCount;

    pFPGA_RxSpBuff = (uint8_t *)data;
    FPGA_RxSpCount = 4096;

    while(FPGA_RX_SPECTROMETER_SIGNAL_REG_PORT&FPGA_RX_SPECTROMETER_SIGNAL_REG_RISE_PIN);
    while(!(FPGA_RX_SPECTROMETER_SIGNAL_REG_PORT&FPGA_RX_SPECTROMETER_SIGNAL_REG_RISE_PIN));
    while(FPGA_RxSpCount--)
    {
        //等待下降沿
        while(FPGA_RX_SPECTROMETER_SIGNAL_REG_PORT&FPGA_RX_SPECTROMETER_SIGNAL_REG_CLK_PIN);
        while(!(FPGA_RX_SPECTROMETER_SIGNAL_REG_PORT&FPGA_RX_SPECTROMETER_SIGNAL_REG_CLK_PIN));
        *pFPGA_RxSpBuff++ = FPGA_RX_SPECTROMETER_DATA_REG_PIN;
        __no_operation();
    }
}

int8_t FPGA_parseUSB_Buffer(uint8_t *RxCommand,uint8_t *RxParameter,uint8_t *RxParameterCount)
{
    uint8_t i;
    uint8_t index55;
    uint8_t index;
    uint8_t crc;
    uint8_t FPGA_USCI_RxDataLen = 0;

    /*
     * 判断是否接到新数据
     */
    for(i=0;i<FPGA_USCI_RxBuff_LEN;i++)
    {
        if(FPGA_USCI_RxBuff[i] == 0x55)//循环寻找0x55
        {
            uint8_t currentCount;
            index55 = i;
            FPGA_USCI_RxBuff[index55] = 0x00;
            index = FPGA_getQueueIndex(index55+1);//定位0xcc的位置
            do{
                currentCount = FPGA_USCI_RxBuffCount;
                __delay_cycles(MSP430_FREQUENCY/1000);//等待10ms
            }
            while(currentCount != FPGA_USCI_RxBuffCount);
            if(FPGA_USCI_RxBuff[index] == 0xcc)//判断下一位是否是0xcc
            {
                //禁用中断
                USCI_A_UART_disableInterrupt(FPGA_USCI_BASE,USCI_A_UART_RECEIVE_INTERRUPT);
                /*
                 * 取出长度信息
                 */
                index = FPGA_getQueueIndex(index55+2);//定位lenLow的位置
                FPGA_USCI_RxDataLen = FPGA_USCI_RxBuff[index];

                index = FPGA_getQueueIndex(index55+3);//定位lenHigh的位置
                FPGA_USCI_RxDataLen |= ((uint16_t)FPGA_USCI_RxBuff[index])<<8;
                break;
            }
        }
    }
    if(FPGA_USCI_RxDataLen==0)
    {
        return 0;//没有新数据
    }

    /*
     * 计算校验和
     */
    crc = 0x55;
    for(i=1;i<FPGA_USCI_RxDataLen-3;i++)
    {
        index = FPGA_getQueueIndex(index55+i);//定位每一个数计算校验和
//#ifdef __DEBUG
//        FPGA_sendStrLen(&FPGA_USCI_RxBuff[index],1);
//#endif
        crc += FPGA_USCI_RxBuff[index];
    }

    index = FPGA_getQueueIndex(index55+FPGA_USCI_RxDataLen-3);//定位校验和的位置
    if(FPGA_USCI_RxBuff[index]!=crc)
    {
        uint8_t dbgCrc[2];
        dbgCrc[0] = FPGA_USCI_RxBuff[index];
        dbgCrc[1] = crc;
        printfDBG(dbgCrc,2);
        memset(FPGA_USCI_RxBuff, 0, FPGA_USCI_RxBuff_LEN);
        FPGA_USCI_RxBuffCount = 0;
        USCI_A_UART_enableInterrupt(FPGA_USCI_BASE,USCI_A_UART_RECEIVE_INTERRUPT);//使能位置位
        return -1;//校验和不匹配
    }

    /*
     * 取出命令信息与参数信息
     */
    index = FPGA_getQueueIndex(index55+4);//定位cmd的位置
    *RxCommand = FPGA_USCI_RxBuff[index];
    index = FPGA_getQueueIndex(index55+5);//定位参数的位置
    memset(RxParameter, 0,FPGA_RxParameter_Length);
    for(i=index;i<FPGA_USCI_RxDataLen-3;i++)
    {
        RxParameter[i-index] = FPGA_USCI_RxBuff[i];
    }
    /*
     * 保存参数长度
     */
    *RxParameterCount = FPGA_USCI_RxDataLen-8;

    /*
     * 该取出的数据都取完了，清空缓存
     */
    memset(FPGA_USCI_RxBuff, 0, FPGA_USCI_RxBuff_LEN);
    FPGA_USCI_RxBuffCount = 0;
    //使能中断
    USCI_A_UART_enableInterrupt(FPGA_USCI_BASE,USCI_A_UART_RECEIVE_INTERRUPT);//使能位置位

    return 1;
}

uint8_t FPGA_getQueueIndex(uint8_t index)
{
    if((index)<FPGA_USCI_RxBuff_LEN){//判断往后数index位是否超出缓存
        return index;//未超出
    }else{
        return index-FPGA_USCI_RxBuff_LEN;//超出
    }
}

void FPGA_getRS485(uint8_t *para,uint8_t paraLen,uint8_t *buff,uint8_t *buffCount,uint16_t uartBaseAddress)
{
    *buffCount = 0;
    pFPGA_RxBuff = buff;
    pFPGA_RxCount = buffCount;
    uint16_t Timeing;
    uint8_t lastCount = 0;
    uint8_t cmdStr[6] = {0x55,0xcc,0x01,0x02,0x36,0};
    uint8_t endCmd[9] = {0x55,0xCC,0x09,0x00,0x36,0x00,0x60,0x00,0x00};
    //--------------------发送开始命令--------------------
    cmdStr[5] = para[0];            //将RS485/RS232代号存到命令中
    if(uartBaseAddress != FPGA_USCI_BASE)
    {
        FPGA_sendStrLen(cmdStr,6);      //开启对应的RS485/RS232
    }
    __delay_cycles(MSP430_FREQUENCY);   //等待开启，1000毫秒
    isRxFromRS485 = 1;              //改变串口接收模式为RS485
    FPGA_sendStrLen(&para[1],paraLen-1);//发送数据到RS485/RS232
    //--------------------获取数据---------------------
    Timeing = 5000;//等待5000个0.001秒
    while(*pFPGA_RxCount==0){//等待数据开始返回
        printfDBG("WaitData",8);
        __delay_cycles(MSP430_FREQUENCY/1000);
        Timeing--;
        if(Timeing == 0)
        {
            printfDBG("5sTimeOut",9);
            break;
        }
    }
    while(lastCount != *pFPGA_RxCount)//等待数据返回完毕
    {
        lastCount = *pFPGA_RxCount;
        __delay_cycles(MSP430_FREQUENCY/100);
    }
    isRxFromRS485 = 0;//改变串口接收模式为USB
    //------------------发送结束命令--------------------
    FPGA_sendStrLen(endCmd,9);//关闭RS485/RS232模式
}

void FPGA_sendStr(uint8_t *str)
{
    for(;*str != '\0';str++)
    {
        USCI_A_UART_transmitData(FPGA_USCI_BASE,*str);
    }
}

void FPGA_sendStrLen(uint8_t *str,uint16_t len)
{
    uint16_t i;
    for(i=0;i<len;i++)
    {
        USCI_A_UART_transmitData(FPGA_USCI_BASE,str[i]);
    }
}

//******************************************************************************
//
//This is the USCI_A3 interrupt vector service routine.
//
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A3_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(USCI_A3_VECTOR)))
#endif
void FPGA_USCI_A3_ISR (void)
{
    switch (__even_in_range(UCA3IV,4)){
        case 2://Vector 2 - RXIFG
        {
            if(!isRxFromRS485)
            {
                FPGA_USCI_RxBuff[FPGA_USCI_RxBuffCount++] = USCI_A_UART_receiveData(FPGA_USCI_BASE);
                if(FPGA_USCI_RxBuffCount >= FPGA_USCI_RxBuff_LEN)
                {
                    FPGA_USCI_RxBuffCount=0;
                }
            }
            else
            {
                *pFPGA_RxBuff++ = USCI_A_UART_receiveData(FPGA_USCI_BASE);
                (*pFPGA_RxCount)++;
            }
            break;
        }
        default: break;
    }
}
